home *** CD-ROM | disk | FTP | other *** search
- /***
- * hyperUtil.c
- *
- * Some useful routine for writing hypercard xcmds and funcs.
- *
- * Gordon Watts July '91 Copyright.
- *
- ***/
- #include <HyperXCmd.h>
- #include "hyperUtil.h"
- #include <Aliases.h>
- /**
- * strToHandle
- *
- * Convert a null terminated string to a handle to pass back to hypercard.
- *
- **/
- Handle strToHandle (XCmdPtr theP, char *theString)
- {
- Handle theHandle;
- register Size theLen = StringLength (theP, theString) + 1;
-
- theHandle = NewHandle (theLen);
- BlockMove (theString, *theHandle, theLen);
-
- return theHandle;
- }
- /**
- * HCProgramToPortAndLoc
- *
- * Convert a Hypercard program name (<zone>:<mac>:<program>) to a
- * port. If that program has more than one port open, we take the
- * first port we find!
- *
- * Assumptions we make:
- *
- **/
- OSErr HCProgramToPortAndLoc (char *theName, LocationNameRec *theLoc,
- PortInfoRec *thePort)
- {
- char *appleZone = 0;
- char *macName = 0;
- char *progName = 0;
- char *theLastChar = 0;
- PPCPortRec thePortSearchSpec;
- IPCListPortsPBRec thePBRec;
- int theErr;
-
- /**
- ** Assemble a location. This is a bit of a pain, as we must
- ** carefully unpack the incomming string...
- **/
-
- /**
- ** First job -- find the end of the incomming string so we don't
- ** run off into memory...
- **/
-
- theLastChar = theName;
- appleZone = theName; /* First thing there... */
- while (*theLastChar != '\0') {
- if (*theLastChar == ':') {
- if (!macName) {
- macName = theLastChar + 1;
- } else if (!progName) {
- progName = theLastChar + 1;
- }
- }
- theLastChar++;
- }
-
- /**
- ** Right, make sure that we got everything...
- **/
-
- if ((progName == 0) || (macName == 0))
- return 1; /* Random error... */
-
- /**
- ** Next, assemble a port record that we can use to specify what
- ** the hell we are looking for... Use a roman script (sorry, guys),
- ** match only names that have our program, and match all types.
- ** That way we will get the first type.
- **/
-
- thePortSearchSpec.nameScript = smRoman;
- thePortSearchSpec.portKindSelector = ppcByString;
- MakePascalStringWLen ((StringPtr) thePortSearchSpec.name, 32, progName,
- (Size)(theLastChar - progName));
- MakePascalStringWLen ((StringPtr) thePortSearchSpec.u.portTypeStr,
- 32, "=", 1);
-
- /**
- ** Next job is to fill in the location record that the guy passed
- ** in. The objString is the mac we wish to connect to. The zone
- ** is the apple zone. We let the type be random... so we set it
- ** to PPCToolBox as defined by IM VI 6 7-23.
- **/
-
- theLoc -> locationKindSelector = ppcNBPLocation;
- {
- register EntityName *theE = &(theLoc -> u.nbpEntity);
-
- MakePascalStringWLen ((StringPtr) &(theE -> objStr), 32,
- macName, (int) (progName - macName - 1));
- MakePascalStringWLen ((StringPtr) &(theE -> typeStr), 32,
- "PPCToolBox", 10);
- MakePascalStringWLen ((StringPtr) &(theE -> zoneStr), 32,
- appleZone, (macName - appleZone - 1));
- }
-
- /**
- ** Right. Finally, we fill in the parameter block we are to pass
- ** to IPCListPorts.
- **/
-
- thePBRec.startIndex = 0;
- thePBRec.requestCount = 1;
- thePBRec.portName = &thePortSearchSpec;
- thePBRec.locationName = theLoc;
- thePBRec.bufferPtr = thePort;
-
- /**
- ** Call the damm routine and try to get the stupid port back!
- **/
-
- theErr = IPCListPorts (&thePBRec, false);
-
- return theErr;
- }
-
- /**
- * MakePascalStringWLen
- *
- * Given a C string, put it into a pascal storage area. We also make
- * sure that the length of the pascal string isn't too long (the caller
- * specifiys the longest length possible). We are passed in the length
- * of the C string... This makes our life simpler...
- *
- **/
- void MakePascalStringWLen (StringPtr theDest, int theDestLen, char *theSrc,
- int theSrcLen)
- {
- theDest[0] = theSrcLen > theDestLen ? theDestLen : theSrcLen;
- BlockMove (theSrc, &(theDest[1]), theDest[0]);
- }
-
- /**
- * AEFromHCProgram
- *
- * Given a HC program name, turn it into an apple event. This isn't
- * too bad; we just have to fool a little with the descriptor types.
- * Code thanks to Kevin at Apple.
- **/
- #define nice
- OSErr AEFromHCProgram (StringPtr theHCProgName,
- AEEventClass theClass,
- AEEventID theEventID, int returnID, long transactionID,
- AppleEvent *theAE)
- {
- #ifdef nice
- AEDesc theAddressDesc;
- register int theErr;
-
- /**
- ** Convert the string into a descriptor & try and make it
- ** into a better type recrod... By passing 'ADDR' as the type
- ** into which we wish to convert the darned string, we let the mac
- ** os (PPC Toolbox) decide if we should do a process serial number or
- ** a real targetID record (for networked destinations).
- **/
-
- theErr = AECoercePtr (typeChar, (Ptr) &(theHCProgName[1]),
- theHCProgName[0], 'ADDR', &theAddressDesc);
- if (theErr != noErr)
- return theErr;
-
- /**
- ** Hey! Next job: create the apple event. Pretty easy, eh?
- **/
-
- theErr = AECreateAppleEvent (theClass, theEventID, &theAddressDesc,
- returnID, transactionID, theAE);
-
- /**
- ** Delete the address descriptor and return.
- **/
-
- return theErr;
- #endif
- #ifdef dumy_too
- register int theErr;
- TargetID theTarget;
- PortInfoRec thePortInfo;
- char string[255];
- AEAddressDesc targetDesc;
-
- /**
- ** Ok.. First job is to convert the thing into location and port
- ** records...
- **/
-
- BlockMove (&(theHCProgName[1]), string, theHCProgName[0]);
- string[theHCProgName[0]] = 0;
-
- theErr = HCProgramToPortAndLoc (string, &(theTarget.location),
- &thePortInfo);
- if (theErr != noErr)
- return theErr;
-
- /**
- ** Next, put the mac name into the target guy...
- **/
-
- theTarget.name = thePortInfo.name;
-
- /**
- ** Next, create a descriptor to hold this thing...
- **/
-
- theErr = AECreateDesc (typeTargetID, (Ptr) &theTarget,
- sizeof(TargetID), &targetDesc);
- if (theErr != noErr)
- return theErr;
-
- /**
- ** Right on. Now we get to create the apple event...
- **/
-
- theErr = AECreateAppleEvent (theClass, theEventID, &targetDesc,
- returnID, transactionID, theAE);
- return theErr;
- #endif
- }
-
- /**
- * makeFileListFmHCF
- *
- * Make a apple event file descriptor list from a hypercard field. This
- * means that we expect all the fields to be <return> seperated (we
- * use call back routines to figure out what the file names are...).
- *
- **/
- OSErr makeFileListFmHCF (XCmdPtr paramPtr, char *cfile_list,
- AEDescList *theFileDL)
- {
- register int theErr, index;
- char *nextFile;
- Str255 aFileName, fullFileName;
- SFTypeList theTypes;
- OSType theFileType;
- FSSpec myFS;
- AliasHandle myAlias;
- AEDesc theAliasDesc;
-
- /**
- ** First, create the descriptor header...
- **/
-
- theErr = AECreateList (0L, 0, false, theFileDL);
- if (theErr != noErr)
- return theErr;
-
- /**
- ** Loop through all return delimited filenames in the input string.
- ** For each one, we must convert it to a typeFSS record and then
- ** we can use it to coerce to a typeAlias descriptor which can
- ** be send to the other guys in this world...
- **/
-
- nextFile = cfile_list;
- index = 0;
-
- while (*nextFile != '\0') {
-
- ReturnToPas (paramPtr, nextFile, aFileName);
- ScanToReturn (paramPtr, &nextFile);
- if (*nextFile != 0) nextFile++;
-
- theFileType = ' ';
-
- /**
- ** Try to make the FSSpec from the file. If we fail, then
- ** ask the user to point out the file to us.
- **/
-
- theErr = FSMakeFSSpec (0, 0, aFileName, &myFS);
- {
- Str255 theNum;
-
- NumToStr (paramPtr, theErr, theNum);
- SetGlobal (paramPtr, (StringPtr) "\ptheErrFS",
- PasToZero (paramPtr, theNum));
- }
-
- if (theErr != noErr) {
- if (GetFilePath(paramPtr, (StringPtr) aFileName, 0, theTypes,
- true, &theFileType, (StringPtr) fullFileName))
- theErr = FSMakeFSSpec (0, 0, fullFileName, &myFS);
- }
- if (theErr != noErr)
- return theErr;
-
- index++;
-
- /**
- ** Next, create an alias type o record...
- **/
-
- theErr = NewAlias (0L, &myFS, &myAlias);
- if (theErr != noErr)
- return theErr;
-
- /**
- ** And add it to the list...
- **/
-
- theErr = AEPutPtr (theFileDL, index, typeAlias, (Ptr) *myAlias,
- GetHandleSize ((Handle) myAlias));
- if (theErr != noErr)
- return theErr;
-
- {
- AEDesc theJunk;
- Str255 string;
- ProcPtr proc, proc1;
- long refcon;
- Boolean isdesc;
-
- /* theErr = AECreateDesc (typeFSS, (Ptr) &myFS, sizeof (FSSpec),
- &theJunk);
- */
- theErr = AECoercePtr (typeFSS, (Ptr) &myFS, sizeof(FSSpec),
- typeAlias, &theJunk);
- NumToStr (paramPtr, theErr, string);
- SetGlobal (paramPtr, (StringPtr) "\ptheErrC",
- PasToZero (paramPtr, string));
- proc = 0;
- theErr = AEGetCoercionHandler (typeFSS, typeAlias,
- &proc, &refcon, &isdesc, false);
- proc1 = 0;
- theErr = AEGetCoercionHandler (typeAlias, typeFSS,
- &proc1, &refcon, &isdesc, true);
- BoolToStr (paramPtr, ((proc1 != 0) || (proc != 0)), string);
- SetGlobal (paramPtr, (StringPtr) "\phandlerIs",
- PasToZero (paramPtr, string));
- }
- }
-
- /**
- ** Some basic error checking -- make sure we sent something...
- **/
-
- if (index) {
- return noErr;
- } else {
- return 1;
- }
- }
-